package com.sky.advice;

import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.AutoFill;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/*
 *    用于根据Mapper层方法操作类型 UPDATE | INSERT 自动为增加对应默认属性的切面类
 *        createTime | updateTime | createUser | updateUser
 * */

//@Aspect
//@Component
@Slf4j
public class AutoFillAdvice {

    // 配合自定义注解实现指定字段自动注入
    @Before("execution(* com..mapper.*.*(..)) && @annotation(com.sky.enumeration.AutoFill)")
    public void AutoFill(JoinPoint joinPoint) {
        log.info("自动注入增强启动！");
        // 获取方法签名对象
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取该方法的操作类型 INSERT | UPDATE
        OperationType operationType = signature.getMethod().getAnnotation(AutoFill.class).value();

        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) return;

        // 需要注入字段的方法的参数都为实体类
        // 获取首个参数即可
        Object arg = args[0];

        // 当前时间
        LocalDateTime now = LocalDateTime.now();
        // 执行操作的人员id
        Long id = BaseContext.getCurrentId();
        BaseContext.removeCurrentId();

        // 根据方法操作类型配合反射插入对应字段
        if (operationType == OperationType.INSERT) {
            try {
                // 获取实体类的set方法
                Method setCreateUser = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateUser = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                Method setCreateTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setUpdateTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);

                // 执行方法
                setCreateUser.invoke(arg,id);
                setUpdateUser.invoke(arg,id);
                setCreateTime.invoke(arg,now);
                setUpdateTime.invoke(arg,now);

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (operationType == OperationType.UPDATE) {
            try {
                arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class).invoke(arg,id);
                arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,LocalDateTime.class).invoke(arg,now);

            } catch (Exception e){
                e.printStackTrace();
            }
        }


    }

}
